﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using System.Collections;
using System.Data;
using System.Web.UI.WebControls;
using System.Web.UI;
using Microsoft.SharePoint.WebControls;

namespace PhilWicklund.com.LimitedAccessReport
{
	public class LimitedAccessReport: System.Web.UI.WebControls.WebControl
	{
		protected override void CreateChildControls()
		{
			SPWeb web = SPContext.Current.Web;

			SPRoleDefinitionCollection roleDefinitions = web.RoleDefinitions;

			Hashtable principals = new Hashtable();

			foreach (SPRoleAssignment assignment in web.RoleAssignments)
			{
				SPRoleDefinitionBindingCollection bindings = assignment.RoleDefinitionBindings;
				foreach (SPRoleDefinition definition in bindings)
				{
					if (definition.Name == "Limited Access" && bindings.Count == 1)
					{
						principals.Add(assignment.Member, new List<LimitedObject>());
					}
				}
			}

			Hashtable names = new Hashtable();
			foreach (SPPrincipal principal in principals.Keys)
			{
				names.Add(principal.Name, principal);
			}

			AddFolders(web.RootFolder, ref names, ref principals);

			foreach (SPList list in web.Lists)
			{
				if (list.HasUniqueRoleAssignments)
				{
					foreach (SPPrincipal principal in names.Values)
					{
						SPRoleAssignment assignment = new SPRoleAssignment(principal);
						try
						{
							assignment = list.RoleAssignments.GetAssignmentByPrincipal(principal);
						}
						catch (ArgumentException) { continue; }

						SPRoleDefinitionBindingCollection bindings = assignment.RoleDefinitionBindings;
						foreach (SPRoleDefinition definition in bindings)
						{
							if (definition.Name != "Limited Access")
							{
								string url = "";
								if (list.DefaultViewUrl.StartsWith("/"))
									url = "<a href=\"" + list.ParentWeb.Site.Url + list.DefaultViewUrl + "\">" + list.DefaultViewUrl + "</a>";
								else
									url = "<a href=\"" + list.ParentWeb.Site.Url + "/" + list.DefaultViewUrl + "\">" + list.DefaultViewUrl + "</a>";
								List<LimitedObject> urls = principals[principal] as List<LimitedObject>;
								urls.Add(new LimitedObject(list.ID.ToString(), definition.Name, url, list.Title, "", LimitedObject.ObjectType.List));
								principals[principal] = urls;
							}
						}

					}
				}

				foreach (SPListItem item in list.Items)
				{
					if (item.HasUniqueRoleAssignments)
					{
						foreach (SPPrincipal principal in names.Values)
						{
							SPRoleAssignment assignment = new SPRoleAssignment(principal);
							try
							{
								assignment = item.RoleAssignments.GetAssignmentByPrincipal(principal);
							}
							catch (ArgumentException) { continue; }

							SPRoleDefinitionBindingCollection bindings = assignment.RoleDefinitionBindings;
							foreach (SPRoleDefinition definition in bindings)
							{
								if (definition.Name != "Limited Access")
								{
									string url = "";
									if (list.DefaultViewUrl.StartsWith("/"))
										url = "<a href=\"" + list.ParentWeb.Site.Url + list.DefaultViewUrl.Remove(list.DefaultViewUrl.LastIndexOf("/")) + "/dispform.aspx?id=" + item.ID + "\">" + item.Url + "</a>";
									else
										url = "<a href=\"" + list.ParentWeb.Site.Url + "/" + list.DefaultViewUrl.Remove(list.DefaultViewUrl.LastIndexOf("/")) + "/dispform.aspx?id=" + item.ID + "\">" + item.Url + "</a>";

									string itemTitle = item.Title;
									if (itemTitle == "")
									{
										try
										{
											itemTitle = item["Name"].ToString();
										}
										catch (Exception) { }
									}
									List<LimitedObject> urls = principals[principal] as List<LimitedObject>;
									urls.Add(new LimitedObject(item.ID.ToString(), definition.Name, url, item.ParentList.Title, itemTitle, LimitedObject.ObjectType.ListItem));
									principals[principal] = urls;
								}
							}

						}
					}
				}
			}

			DataTable tblData = new DataTable();
			tblData.Columns.Add("Name");
			tblData.Columns.Add("Role");
			tblData.Columns.Add("Type");
			tblData.Columns.Add("ListTitle");
			tblData.Columns.Add("ItemTitle");
			tblData.Columns.Add("URL");
			tblData.Columns.Add("ID");

			foreach (SPPrincipal principal in principals.Keys)
			{
				List<LimitedObject> los = principals[principal] as List<LimitedObject>;
				if (los.Count == 0 && web.Webs.Count != 0)
					tblData.Rows.Add(
						principal.Name,
						"No Permissions", "", "", "", "No permissions on this site, check child sites", "");
				else if (los.Count == 0 && web.Webs.Count == 0)
					tblData.Rows.Add(
						principal.Name,
						"No Permissions", "", "", "", "This account is orphaned and should be removed from this site", "");
				foreach (LimitedObject lo in los)
				{
					tblData.Rows.Add(
						principal.Name,
						lo.DefinitionName,
						lo.Type.ToString(),
						lo.ListTitle,
						lo.ItemTitle,
						lo.Url,
						lo.ID);
				}
			}

			Table table = new Table();
			table.Width = Unit.Percentage(100);
			table.CellPadding = 0;
			table.CellSpacing = 0;
			TableRow tr = new TableRow();
			TableCell td = new TableCell();
			td.Attributes.Add("background-color", "#999999");
			td.Attributes.Add("font-weight", "bold");
			td.Attributes.Add("color", "white");
			td.Attributes.Add("align", "center");
			td.Attributes.Add("padding", "4px 0px 4px 0px");
			td.HorizontalAlign = HorizontalAlign.Center;
			td.Controls.Add(new LiteralControl("Limited Access Breakdown"));
			tr.Cells.Add(td);
			//table.Rows.Add(tr);

			SPGridView sgvGrid = new SPGridView();
			sgvGrid.Width = Unit.Percentage(100);
			sgvGrid.ID = "LAGrid";
			sgvGrid.CssClass = "ms-alternatingstrong";
			sgvGrid.AutoGenerateColumns = false;

			BoundField col = new BoundField();
			col.DataField = "Name";
			col.SortExpression = "Name";
			col.HeaderText = "Account Name";
			sgvGrid.Columns.Add(col);

			col = new BoundField();
			col.DataField = "Role";
			col.SortExpression = "Role";
			col.HeaderText = "Role";
			sgvGrid.Columns.Add(col);

			col = new BoundField();
			col.DataField = "Type";
			col.SortExpression = "Type";
			col.HeaderText = "Object Type";
			sgvGrid.Columns.Add(col);
			 
			col = new BoundField();
			col.DataField = "ListTitle";
			col.SortExpression = "ListTitle";
			col.HeaderText = "List Title";
			sgvGrid.Columns.Add(col);

			col = new BoundField();
			col.DataField = "ItemTitle";
			col.SortExpression = "ItemTitle";
			col.HeaderText = "Item Title";
			sgvGrid.Columns.Add(col);

			col = new BoundField();
			col.HtmlEncode = false;
			col.DataField = "URL";
			col.SortExpression = "URL";
			col.HeaderText = "URL";
			sgvGrid.Columns.Add(col);

			col = new BoundField();
			col.DataField = "ID";
			col.SortExpression = "ID";
			col.HeaderText = "ID";
			sgvGrid.Columns.Add(col);

			DataView dataView = new DataView(tblData);
			sgvGrid.DataSource = dataView;

			sgvGrid.DataBind();
			tr = new TableRow();
			td = new TableCell();
			td.Controls.Add(sgvGrid);
			tr.Cells.Add(td);
			table.Rows.Add(tr);

			this.Controls.Add(table);
		}

		private void AddFolders(SPFolder folder, ref Hashtable names, ref Hashtable principals)
		{
			foreach (SPFolder subFolder in folder.SubFolders)
			{
				try
				{
					if (subFolder.Item.HasUniqueRoleAssignments)
					{
						foreach (SPPrincipal principal in names.Values)
						{
							SPRoleAssignment assignment = new SPRoleAssignment(principal);
							try
							{
								assignment = subFolder.Item.RoleAssignments.GetAssignmentByPrincipal(principal);
							}
							catch (ArgumentException) { continue; }

							SPRoleDefinitionBindingCollection bindings = assignment.RoleDefinitionBindings;
							foreach (SPRoleDefinition definition in bindings)
							{
								if (definition.Name != "Limited Access")
								{
									string url = "";
									if (subFolder.Url.StartsWith("/"))
										url = "<a href=\"" + subFolder.ParentWeb.Site.Url + subFolder.Url + "\">" + subFolder.Url + "</a>";
									else
										url = "<a href=\"" + subFolder.ParentWeb.Site.Url + "/" + subFolder.Url + "\">" + subFolder.Url + "</a>";
									List<LimitedObject> urls = principals[principal] as List<LimitedObject>;
									string listName = "";
									try
									{
										listName = subFolder.Item.ParentList.Title;
									}
									catch (Exception) { }
									urls.Add(new LimitedObject(subFolder.Item.ID.ToString(), definition.Name, url, listName, subFolder.Name, LimitedObject.ObjectType.Folder));
									principals[principal] = urls;
								}
							}
						}
					}
				}
				catch (Exception) { continue; }
				finally
				{
					if (subFolder.SubFolders.Count > 0)
						AddFolders(subFolder, ref names, ref principals);
				}
			}
		}
	}
}
